#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <getch.h>
#include "network.h"


//将PASV与LIST-al封装成一个函数
int pasv_list(Network* nw)
{
	char buf[256]={};
	sprintf(buf,"PASV\n");
	nsend(nw,buf,strlen(buf));
	
	bzero(buf,sizeof(buf));
	nrecv(nw,buf,sizeof(buf));
	puts(buf);

	unsigned char ip1,ip2,ip3,ip4,port1,port2;
	sscanf(strchr(buf,'(')+1,"%hhu,%hhu,%hhu,%hhu,%hhu,%hhu",&ip1,&ip2,&ip3,&ip4,&port1,&port2);
	sprintf(buf,"%hhu.%hhu.%hhu.%hhu",ip1,ip2,ip3,ip4);

	Network* data_nw =open_network('c',SOCK_STREAM,buf,port1*256+port2);
	printf("connet success fd =%d\n",data_nw->fd);
	
	sprintf(buf,"LIST -al\n");
	nsend(nw,buf,strlen(buf));
	
	bzero(buf,sizeof(buf));
	nrecv(nw,buf,sizeof(buf));
	puts(buf);
	
	int ret =0;
	bzero(buf,sizeof(buf));
	while(ret = nrecv(data_nw,buf,sizeof(buf)))
	{
		printf("%s",buf);
		bzero(buf,sizeof(buf));
		}
	printf("\n");
	
	close_network(data_nw);
	
	
	bzero(buf,sizeof(buf));
	nrecv(nw,buf,sizeof(buf));
	puts(buf);
}

//中间处理过程函数
int deal(Network* nw)
{
	char buf[256]={};
	sprintf(buf,"SYST\n");
	nsend(nw,buf,strlen(buf));
	
	bzero(buf,sizeof(buf));
	nrecv(nw,buf,sizeof(buf));
	puts(buf);

	sprintf(buf,"OPTS UTF8 ON\n");
	nsend(nw,buf,strlen(buf));
	
	bzero(buf,sizeof(buf));
	nrecv(nw,buf,sizeof(buf));
	puts(buf);

	sprintf(buf,"PWD\n");
	nsend(nw,buf,strlen(buf));
	
	bzero(buf,sizeof(buf));
	nrecv(nw,buf,sizeof(buf));
	puts(buf);
	pasv_list(nw);
}

//连接函数
int login(Network* nw)
{	
	for(;;)
	{
	char buf[256]={};
	char name[20]={};
	char pass[10]={};
	printf(">输入用户名\n");
	printf(">");
	gets(name);
	sprintf(buf,"USER %s\n",name);
	nsend(nw,buf,strlen(buf));
	bzero(buf,sizeof(buf));
	nrecv(nw,buf,sizeof(buf));
	puts(buf);
	
	printf(">输入密码\n");
	printf(">");
	//通过getch()不显示获取密码
	for(int i=0;i<20;i++)
		{
			char c = getch();
			if('\n' == c)
			{
				break;
				}
			pass[i] = c;
			}
	sprintf(buf,"PASS %s\n",pass);
	nsend(nw,buf,strlen(buf));
	bzero(buf,sizeof(buf));
	nrecv(nw,buf,sizeof(buf));
	puts(buf);
	if(0 != strncmp(buf,"530",3))
	{
		break;
		}
	}
}

//命令函数
int get_cmd(Network* nw)
{
	for(;;)
	{
		char cmd[100]={};
		char filename[100]={};
		char path[100]={};
		char buf[256]={};
		printf(">");
		gets(cmd);
		//进入服务器的文件夹
		if(0 == strncmp(cmd,"cd",2))
		{
			char temp[3]={};
			sscanf(cmd,"%s%s",temp,filename);
				
			printf("%s\n",filename);
			sprintf(buf,"CWD %s\n",filename);
			nsend(nw,buf,strlen(buf));	
			bzero(buf,sizeof(buf));
			nrecv(nw,buf,sizeof(buf));
			puts(buf);
			sprintf(buf,"PWD\n");
			nsend(nw,buf,strlen(buf));
			
			bzero(buf,sizeof(buf));
			nrecv(nw,buf,sizeof(buf));
			puts(buf);
			pasv_list(nw);
		}
		//下载服务端文件
		else if(0 == strncmp(cmd,"get",3))
		{
			char temp[4]={};
			sscanf(cmd,"%s%s",temp,filename);
			
			sprintf(buf,"TYPE I\n");
			nsend(nw,buf,strlen(buf));
	
			bzero(buf,sizeof(buf));
			nrecv(nw,buf,sizeof(buf));
			puts(buf);

			sprintf(buf,"SIZE %s\n",filename);
			nsend(nw,buf,strlen(buf));
	
			bzero(buf,sizeof(buf));
			nrecv(nw,buf,sizeof(buf));
			puts(buf);
	
			sprintf(buf,"MDTM %s\n",filename);
			nsend(nw,buf,strlen(buf));
	
			bzero(buf,sizeof(buf));
			nrecv(nw,buf,sizeof(buf));
			puts(buf);
			
			sprintf(buf,"PASV\n");
			nsend(nw,buf,strlen(buf));
	
			bzero(buf,sizeof(buf));
			nrecv(nw,buf,sizeof(buf));
			puts(buf);
			
			unsigned char ip1,ip2,ip3,ip4,port1,port2;
			sscanf(strchr(buf,'(')+1,"%hhu,%hhu,%hhu,%hhu,%hhu,%hhu",&ip1,&ip2,&ip3,&ip4,&port1,&port2);
			sprintf(buf,"%hhu.%hhu.%hhu.%hhu",ip1,ip2,ip3,ip4);

			Network* data_nw =open_network('c',SOCK_STREAM,buf,port1*256+port2);		
			printf("connet success fd =%d\n",data_nw->fd);
	
			sprintf(buf,"RETR %s\n",filename);
			nsend(nw,buf,strlen(buf));
	
			bzero(buf,sizeof(buf));
			nrecv(nw,buf,sizeof(buf));
			puts(buf);
			
			sprintf(buf,"/home/zhizhen/download/%s",filename);
			int fd= open(buf,O_WRONLY|O_CREAT|O_TRUNC,0644);
			if(0>fd)
			{
				perror("open");
				return -1;
			}
			int ret =0;
			bzero(buf,sizeof(buf));
			while(ret = nrecv(data_nw,buf,sizeof(buf)))
			{
				write(fd,buf,ret);
			}
	
			bzero(buf,sizeof(buf));
			nrecv(nw,buf,sizeof(buf));
			puts(buf);
	
			close_network(data_nw);
			close(fd);
			
			continue;
			}
		//上传至服务端文件
		else if(0 == strcmp("put",cmd))
		{
			for(;;)
			{
				printf(">");
				gets(buf);
				//查看客户端当前文件夹下的文件
				if(0 == strncmp(buf,"ls",2))
				{
					system("ls");
					continue;
				}
				//进入客户端当前文件夹下的文件
				else if(0 == strcmp("cd",buf))
				{
					char temp[2]={};
					sscanf(buf,"%s%s",temp,path);
					chdir(path);
					continue;
				}
				//上传文件
				else if(0 == strncmp(buf,"put",3))
				{
					char temp[4]={};
					sscanf(buf,"%s%s",temp,filename);
					printf("%s\n",filename);
					
					
					
					sprintf(buf,"SIZE %s\n",filename);
					nsend(nw,buf,strlen(buf));
	
					bzero(buf,sizeof(buf));
					nrecv(nw,buf,sizeof(buf));
					puts(buf);
					
					sprintf(buf,"PASV\n");
					nsend(nw,buf,strlen(buf));
	
					bzero(buf,sizeof(buf));
					nrecv(nw,buf,sizeof(buf));
					puts(buf);
			
					unsigned char ip1,ip2,ip3,ip4,port1,port2;
					sscanf(strchr(buf,'(')+1,"%hhu,%hhu,%hhu,%hhu,%hhu,%hhu",&ip1,&ip2,&ip3,&ip4,&port1,&port2);
					sprintf(buf,"%hhu.%hhu.%hhu.%hhu",ip1,ip2,ip3,ip4);

					Network* data_nw =open_network('c',SOCK_STREAM,buf,port1*256+port2);		
					printf("connet success fd =%d\n",data_nw->fd);
					
					sprintf(buf,"STOR %s\n",filename);
					nsend(nw,buf,strlen(buf));

					int fd = open(filename,O_RDONLY);
					if(0>fd)
					{
						perror("open");
						continue;
					}
					
					
					int ret =0;
					while(ret = read(fd,buf,sizeof(buf)))
					{
						nsend(data_nw,buf,ret);
					}
					close_network(data_nw);
					close(fd);
					
					bzero(buf,sizeof(buf));
					nrecv(nw,buf,sizeof(buf));
					puts(buf);
					
					bzero(buf,sizeof(buf));
					nrecv(nw,buf,sizeof(buf));
					puts(buf);

					
					
					sprintf(buf,"PASV\n");
					nsend(nw,buf,strlen(buf));
					
					bzero(buf,sizeof(buf));
					nrecv(nw,buf,sizeof(buf));
					puts(buf);
					
	
					sscanf(strchr(buf,'(')+1,"%hhu,%hhu,%hhu,%hhu,%hhu,%hhu",&ip1,&ip2,&ip3,&ip4,&port1,&port2);
					sprintf(buf,"%hhu.%hhu.%hhu.%hhu",ip1,ip2,ip3,ip4);
	
					data_nw =open_network('c',SOCK_STREAM,buf,port1*256+port2);
					printf("connet success fd =%d\n",data_nw->fd);
					sprintf(buf,"LIST -al\n");
					nsend(nw,buf,strlen(buf));
	
					bzero(buf,sizeof(buf));
					nrecv(nw,buf,sizeof(buf));
					puts(buf);
	
					ret =0;
					bzero(buf,sizeof(buf));
					while(ret = nrecv(data_nw,buf,sizeof(buf)))
					{
						printf("%s",buf);
						bzero(buf,sizeof(buf));
						}
					printf("\n");
	
					close_network(data_nw);
	
	
					bzero(buf,sizeof(buf));
					nrecv(nw,buf,sizeof(buf));
					puts(buf);
						}
					}
			}
		else if(0 == strncmp(cmd,"quit",4))
		{
			return -1;
		}
		else
		{
			printf("无效的操作符!\n");
			continue;
			}
		}
	}

//链接服务端
int ftp_connect(char* ip)
{
	Network* nw = open_network('c',SOCK_STREAM,ip,21);
	if(NULL == nw)
	{
		printf("先输入IP地址!");
		return -1;
		}
	char buf[256]={};
	nrecv(nw,buf,sizeof(buf));
	puts(buf);
	login(nw);
	deal(nw);
	get_cmd(nw);
	}

//通过main函数参数进入
int main(int arcv,char* argv[])
{
	if(2!=arcv)
	{
		printf("User:ip\n");
		}
	else
	{
		ftp_connect(argv[1]);
		}
}

